package com.example.starter.amazon.template;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateUtil;
import com.amazonaws.HttpMethod;
import com.amazonaws.services.s3.AmazonS3;
import com.amazonaws.services.s3.model.ObjectMetadata;
import com.example.starter.amazon.configure.AmazonS3Properties;
import com.example.starter.amazon.pojo.OssResponse;
import com.example.starter.amazon.rule.OssRule;
import lombok.RequiredArgsConstructor;
import lombok.SneakyThrows;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.Date;

/**
 * @author 王令
 * @since 2023/1/12 9:44
 */
@RequiredArgsConstructor
public class OssTemplate {

    private final AmazonS3 amazonS3;
    private final OssRule ossRule;
    private final AmazonS3Properties properties;


    public boolean bucketExists(String bucketName) {
        return amazonS3.doesBucketExistV2(bucketName);
    }

    public void makeBucket(String bucketName) {
        if (!bucketExists(bucketName)) {
            amazonS3.createBucket(bucketName);
        }
    }

    public void removeBucket(String bucketName) {
        if (bucketExists(bucketName)) {
            amazonS3.deleteBucket(bucketName);
        }
    }

    @SneakyThrows
    public OssResponse putObject(String bucketName, String filename, InputStream is, String contentType) {
        String key = ossRule.getKey(filename);
        ObjectMetadata metadata = new ObjectMetadata();
        metadata.setContentLength(is.available());
        metadata.setContentType(contentType);
        amazonS3.putObject(bucketName, key, is, metadata);
        OssResponse response = new OssResponse();
        response.setEndpoint(properties.getEndpoint());
        response.setKey(key);
        response.setFilename(filename);
        response.setBucketName(bucketName);
        response.setUrl(getUrl(bucketName, key));
        return response;
    }

    public OssResponse putObject(String bucketName, String filename, InputStream is) {
        return putObject(bucketName, filename, is, "application/octet-stream");
    }

    public OssResponse putObject(String filename, InputStream is, String contentType) {
        return putObject(properties.getBucket(), filename, is, contentType);
    }

    public OssResponse putObject(String filename, InputStream is) {
        return putObject(properties.getBucket(), filename, is);
    }

    @SneakyThrows
    public OssResponse putObject(MultipartFile multipartFile) {
        return putObject(multipartFile.getOriginalFilename(), multipartFile.getInputStream(),
                multipartFile.getContentType());
    }

    public void deleteObject(String bucketName, String key) {
        amazonS3.deleteObject(bucketName, key);
    }

    public void deleteObject(String key) {
        amazonS3.deleteObject(properties.getBucket(), key);
    }

    public boolean objectExists(String bucketName, String key) {
        return amazonS3.doesObjectExist(bucketName, key);
    }

    public boolean objectExists(String key) {
        return objectExists(properties.getBucket(), key);
    }

    public String getUrl(String bucketName, String key) {
        return amazonS3.getUrl(bucketName, key).toString();
    }

    public String getUrl(String key) {
        return getUrl(properties.getBucket(), key);
    }

    // 生成预签名url
    public OssResponse generatePreSignedUrl(String bucketName, String filename, Date expiration, HttpMethod method) {
        String key = ossRule.getKey(filename);
        String url = amazonS3.generatePresignedUrl(bucketName, key, expiration, method).toString();
        OssResponse response = new OssResponse();
        response.setBucketName(bucketName);
        response.setFilename(filename);
        response.setKey(key);
        response.setEndpoint(properties.getEndpoint());
        response.setUrl(url);
        return response;
    }

    public OssResponse generatePreSignedUrl(String bucketName, String filename, Date expiration) {
        return generatePreSignedUrl(bucketName, filename, expiration, HttpMethod.PUT);
    }

    public OssResponse generatePreSignedUrl(String bucketName, String filename, int expiration, DateField field) {
        return generatePreSignedUrl(bucketName, filename, DateUtil.offset(DateUtil.date(), field, expiration));
    }

    public OssResponse generatePreSignedUrl(String bucketName, String filename) {
        return generatePreSignedUrl(bucketName, filename, DateUtil.offsetDay(DateUtil.date(), 7));
    }

    public OssResponse generatePreSignedUrl(String filename, Date expiration, HttpMethod method) {
        return generatePreSignedUrl(properties.getBucket(), filename, expiration, method);
    }

    public OssResponse generatePreSignedUrl(String filename, Date expiration) {
        return generatePreSignedUrl(properties.getBucket(), filename, expiration);
    }

    public OssResponse generatePreSignedUrl(String filename, int expiration, DateField field) {
        return generatePreSignedUrl(properties.getBucket(), filename, expiration, field);
    }

    public OssResponse generatePreSignedUrl(String filename) {
        return generatePreSignedUrl(properties.getBucket(), filename);
    }
}
